import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;

/*
 * TCSS 422 Process Control Simulator
 * Group Money: Al McKenzie, Michael Pitts, Taylor Zielske
 */

/**
 * A Basic Scheduler that uses round robin scheduling to chose which Process runs next.
 * @author Michael Pitts
 * @version Dec 8, 2011
 */
public class BasicScheduler implements Scheduler {
	
	/** The processes waiting to run. */
	private final Queue<Process> my_waiting_queue;
	
	/** The processes that are blocked and can't run. */
	private final Set<Process> my_blocked_set;
	
	/**
	 * Creates a new Scheduler that implements basic round robin scheduling.
	 */
	public BasicScheduler() {
		my_waiting_queue = new ArrayDeque<Process>();
		my_blocked_set = new HashSet<Process>();
	}

	@Override public Process getNextProcess() {
		if (my_waiting_queue.isEmpty()) {
			return null;
		}
		my_waiting_queue.peek().setStatus(Status.RUNNING);
		return my_waiting_queue.remove();
	}

	@Override public void loadProcesses(final Process[] the_processes) {
		for (Process process: the_processes) {
			if (process.getStatus() == Status.BLOCKED) {
				my_blocked_set.add(process);
			} else {
				my_waiting_queue.add(process);
			}
		}
	}

	@Override public void removeProcess(final Process the_process) {
		my_waiting_queue.remove(the_process);
		my_blocked_set.remove(the_process);
	}

	@Override public int processesLeft() {
		return my_waiting_queue.size() + my_blocked_set.size();
	}

	@Override public void blockProcess(final Process the_process) {
		the_process.setStatus(Status.BLOCKED);
		my_waiting_queue.remove(the_process);
		my_blocked_set.add(the_process);
	}

	@Override public void unBlockProcess(final Process the_process) {
		my_blocked_set.remove(the_process);
		my_waiting_queue.add(the_process);
	}

	@Override public void pushProcess(final Process the_process) {
		my_waiting_queue.add(the_process);
	}

	@Override public int getNumberWaiting() {
		return my_waiting_queue.size();
	}

}
